# has a和is a的关系
# student  book  computer
"""
1.has a
    一个类中使用了另外一种自定义的类型
    如student使用computer book

2.类型：
    系统类型：
        str int float
        list dict tuple set
    自定义类型：
        算是自定义的类，都可以将其当成一种类型
        如s = Student()，s是Student类型的对象
"""


class Computer:
    def __init__(self, brand, type, color):
        self.brand = brand
        self.type = type
        self.color = color

    def online(self):
        print("正在使用电脑上网...")

    def __str__(self):
        return self.brand + "---" + self.type + "---" + self.color


class Book:
    def __init__(self, title, author, number):
        self.title = title
        self.author = author
        self.number = number

    def __str__(self):
        return self.title + "---" + self.author + "---" + str(self.number)


class Student:  # has a
    def __init__(self, name, computer, book):
        self.name = name
        self.computer = computer
        self.books = []
        self.books.append(book)

    def borrow_book(self, book):
        for book1 in self.books:  # 选用book1防止与book变量名重合
            if book1.title == book.title:
                print("已经借过此书！")
                break
        # else需要与for循环配对，而不是和if语句配对，否则else块会在每次循环迭代中检查，而不是在循环结束后检查
        # 和if语句配对会导致只要第一本书不匹配，就会直接添加书籍，而不会继续检查后续的书籍
        else:
            # 将参数book添加到列表中
            self.books.append(book)
            print("添加成功")

    def show_book(self):
        for book in self.books:  # book就是一个book对象
            print(book.title)

    # 所有的类都是自定义类型
    def __str__(self):
        return self.name + "---" + str(self.computer) + "---" + str(self.books)


# 创建对象
computer = Computer("mac", "mac pro 2018", "深灰色")
book = Book("仙逆", "耳根", 10)
student = Student("sunhan", computer, book)
print(student)
# 看借了哪些书
student.show_book()
book1 = Book("琅琊榜", "海宴", 5)
student.borrow_book(book1)
print("-" * 15)
student.show_book()
print("\n")

# is a，就是base class，也叫父类或基类
"""
继承：
    Student，Employee,Doctor ----> 都属于人类
    相同代码 ----> 代码冗杂，可读性不高

    将相同代码提取 ----> Person类
      Student,Employee,Doctor -----> 继承Person

    class Student(Person):
        pass
特点：
    1.如果类中不定义__init__,调用父类 super class的__init__
    2.如果类继承父类也需要定义自己的__init__,就需要在当前类的__init__中调用一下父类的__init__
    3.如何调用父类__init__:
        super().__init__(参数)
        super(类名，对象).__init__(参数)
    4.如果父类有eat(),子类也定义一个eat方法，默认搜索的原则：先找当前类，再去找父类
      override：重写（覆盖）
      父类提供的方法不能满足子类的需求，就需要在子类中定义一个同名的方法，这种行为叫做：重写
    5.子类的方法也可以调用父类方法：
        super().方法名(参数)
    6.如果有两个同名的方法，则后面一个方法会覆盖前面一个方法
"""


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eat(self):
        print(self.name + "正在吃饭...")

    def run(self):
        print(self.name + "正在跑步...")


class Student(Person):
    def __init__(self, name, age, grade):
        # 如何调用父类__init__
        super().__init__(name, age)  # super()表示父类对象
        self.grade = grade

    def study(self, course):
        # Student类中并没有定义course属性，正确的是直接使用方法参数course，而不是self.course
        print(f"{self.name}正在学习{course}课程")

    def eat(self, food):
        super().eat()  # 如果还需要父类的eat()方法则可用super()调用
        print(self.name + "正在吃饭，喜欢吃" + food)


class Employee(Person):
    def __init__(self, name, age, salary, manager):
        super().__init__(name, age)
        self.salary = salary  # 继承共同的特点，写入不同的特点
        self.manager = manager


class Doctor(Person):
    def __init__(self, name, age, patients):
        # 与super().__init__(name,age)类似，多了一个self是否在Doctor里的判断
        super(Doctor, self).__init__(name, age)  # 在Python3中是多余的
        self.patients = patients


s = Student("孙涵", 18, "大一")
s.run()
s.study("预防医学")
s.eat("满汉全席")

e = Employee("lily", 45, 7000, "李老板")
e.eat()

list1 = ["张三", "李四", "王五"]
d = Doctor("tom", 38, list1)
d.run()
print("\n")

# 多重继承
"""
python允许多继承，
def 子类（父类1，父类2，...）：
    pass

如果父类中有相同名称方法，搜索顺序：广度优先
"""


class Base:
    def test(self):
        print("-----Base-----")


class A(Base):
    def test(self):
        print("----> AAAAAAAA")


class B(Base):
    def test1(self):
        print("------> BBBBBBBB")


class C(Base):
    def test2(self):
        print("-----> CCCCCCC")


class D(A, B, C):  # D类共同继承了A类,B类和C类
    pass


d = D()
d.test()

# 调用inspect模块里的getmro函数来展示D类继承父类的查找顺序
import inspect

print(inspect.getmro(D))
# 也可以直接调用__mro__方法
print(D.__mro__)